<?php

namespace App\Admin\Controllers;

use App\Admin\Metrics\Examples;
use App\Http\Controllers\Controller;
use Dcat\Admin\Http\Controllers\Dashboard;
use Dcat\Admin\Layout\Column;
use Dcat\Admin\Layout\Content;
use Dcat\Admin\Layout\Row;
use Dcat\Admin\Grid;
use App\Models\Project;
use Dcat\Admin\Widgets\Card;
use Dcat\Admin\Admin;
use App\Models\Cabinet;
use App\Models\CabinetData;
use App\Models\CabinetDataSecond;
use App\Models\CabinetPoint;
use App\Models\CabinetLiveText;
use Illuminate\Http\Request;
use Dcat\Admin\Widgets\Dropdown;
use App\Handlers\WeconHandler;
use Dcat\Admin\Widgets\Tab;
use App\Admin\Metrics\CabinetChildren\ChildrenDonut;
use App\Admin\Metrics\CabinetChildren\ChildrenLine;
use Illuminate\Support\Facades\Redis;

class CabinetDataController extends Controller
{
    const SELF_AUTO_REFRESH = 60;

    public function realtime(Content $content, $projectId, $id = 0)
    {   
        if (empty($id)) {
            $boxes = Cabinet::where('project_id', $projectId)->distinct()->pluck('pid')->toArray();
            foreach ($boxes as $v) {
                if (empty($v)) {
                    continue;
                } else {
                    $box = $v;
                    break;
                }
            }
        } else {
            $box = $id;
        }

        Admin::css('/layui/css/layui.css');
        
        $sessionKey = 'cabinet_realtime_auto_refresh';
        $autoRefresh = session($sessionKey) ? session($sessionKey) : self::SELF_AUTO_REFRESH;
        
        $b = Cabinet::find($box);
        $refresh['autoRefresh'] = $autoRefresh;
        $refresh['key'] = $sessionKey;
        $refresh['title'] = $b['name'];
        $boxes = Cabinet::where('project_id', $projectId)->where('pid', 0)->get()->toArray();
        foreach ($boxes as &$oneBox) {
            $oneBox['url'] = url('admin/cabinet-realtime/'.$projectId.'/'.$oneBox['id']);
        }
        $refresh['boxes'] = $boxes;
        $refresh['status'] = WeconHandler::getBoxStatus($b['machine_code']);
        return $content
            ->body(headmenu($box))
            ->body(view('admin.cabinet.autoRefresh', $refresh))
            ->body($this->realtimeView($box));
    }
    
    protected function realtimeMenuTree($box, $projectId){
        $tab = Tab::make();
        $cabinets = Cabinet::select(['id', 'name', 'pid'])->where('project_id', $projectId)->get()->toArray();
        $menu = [];
        foreach ($cabinets as $k => $v) {
            if (!$v['pid']) {
                if ($v['id'] == $box) {
                    $one['spread'] = true;
                } else {
                    $one['spread'] = false;
                }
                $one['title'] = $v['name'];
                $one['id'] = $v['id'];
                $one['children'] = [];
                $one['isParent'] = true;
                $one['url'] = url('admin/cabinet-realtime').'/'.$projectId."/".$v['id'];
                foreach ($cabinets as $kk => $vv) {
                    if ($v['id'] == $vv['pid']) {
                        $status = $kk==0?true:false;
                        $tab->add($vv['name'], 'sds', $status);
                        $children['spread'] = true;
                        $children['title'] = $vv['name'];
                        $children['id'] = $vv['id'];
                        $children['url'] = url('admin/cabinet-realtime-detail').'/'.$projectId.'/'.$vv['id'];
                        array_push($one['children'], $children);
                    }
                }
            array_push($menu, $one);
            }
        }
        $data['menu'] = json_encode($menu);
        $card = Card::make(view('admin.cabinet.realtimeMenuTree', $data));
        return $card;
        // return $tab->withCard();
    }

    protected function realtimeView($boxId){
        $cabinets = Cabinet::where('pid', $boxId)->where('show', Cabinet::SHOW_YES)->get()->toArray();
        $data = [];
        $cabinetsData = [];

        foreach ($cabinets as $oneCabinet) { 
            $oneCabinetData['name'] = $oneCabinet['name'];
            $oneCabinetData['time'] = date("Y-m-d H:i:s");
            $oneCabinetData['id'] = $oneCabinet['id'];
            $oneCabinetData['detail'] = url('admin/cabinet-realtime-detail').'/'.$oneCabinet['project_id'].'/'.$oneCabinet['id'];

            $points = CabinetPoint::select(['id', 'alias', 'name', 'units', 'decimal'])->where('cabinet_id', $oneCabinet['id'])->get()->keyBy('alias')->toArray();
            $newestCacheKey = Cabinet::CACHE_KEY_.$oneCabinet['id'];
            $newestCache = Redis::get($newestCacheKey);
            if ($newestCache) {
                $newestData = json_decode($newestCache, true);

                $noShowPoint = CabinetPoint::where('cabinet_id', $oneCabinet['id'])->where('realtime_show', 0)->pluck('alias')->toArray();
                if ($noShowPoint) {
                    foreach ($noShowPoint as $oneNoShow) {
                        unset($newestData[$oneNoShow]);
                    }
                }

                $extraText = CabinetLiveText::getTextCache($newestData);
                if ($extraText) {
                    foreach ($extraText as $alias => $name) {
                        $newestData[$alias] = $name;
                    }
                }
                $oneCabinetData['newestData'] = $newestData;
            } else {
                $oneCabinetData['newestData'] = [];
            }
            $oneCabinetData['points'] = $points;
            array_push($cabinetsData, $oneCabinetData);
        }
        $data['cabinetsData'] = $cabinetsData;
        $sessionKey = 'cabinet_realtime_auto_refresh';
        $data['autoRefresh'] = session($sessionKey) ? session($sessionKey) : self::SELF_AUTO_REFRESH;;
        $data['time'] = time();
        $data['boxId'] = $boxId;
        $card = Card::make(view('admin.cabinet.realtime', $data));
        $card->padding('0');
        return $card;
    }

    public function getCabinetRealtimeDataByBox(Request $request){
        $param = $request->all();
        $cabinets = Cabinet::where('pid', $param['boxId'])->get()->toArray();
        $cabinetsData = [];
        foreach ($cabinets as $oneCabinet) {
            $oneCabinetData = [];
            
            $newestCacheKey = Cabinet::CACHE_KEY_.$oneCabinet['id'];
            $newestCache = Redis::get($newestCacheKey);
            if ($newestCache) {
                $newestData = json_decode($newestCache, true);

                $noShowPoint = CabinetPoint::where('cabinet_id', $oneCabinet['id'])->where('realtime_show', 0)->pluck('alias')->toArray();
                if ($noShowPoint) {
                    foreach ($noShowPoint as $oneNoShow) {
                        unset($newestData[$oneNoShow]);
                    }
                }

                $extraText = CabinetLiveText::getTextCache($newestData);
                if ($extraText) {
                    foreach ($extraText as $alias => $name) {
                        $newestData[$alias] = $name;
                    }
                }

                $points = CabinetPoint::select(['id', 'alias', 'name', 'units', 'decimal'])->where('cabinet_id', $oneCabinet['id'])->get()->keyBy('alias')->toArray();
                foreach ($points as $alias => $one) {
                    if ($one['decimal']) {
                        $newestData[$alias] = round($newestData[$alias] / pow(10, intval($one['decimal'])), 3);
                    }
                }

                $oneCabinetData['newestData'] = $newestData;
                $oneCabinetData['time'] = date("Y-m-d H:i:s");
                $oneCabinetData['id'] = $oneCabinet['id'];
            }
            array_push($cabinetsData, $oneCabinetData);
        }
        return response()->json(['code'=>1, 'data' => $cabinetsData, 'msg' => 'success']);
    }

    //*************************************************************************************************
    //*************************************************************************************************

    public function realtimeDetail(Content $content, $projectId, $id = 0)
    {   
        $cabinet = Cabinet::find($id);
        
        $sessionKey = 'cabinet_realtime_detail_auto_refresh';
        $autoRefresh = session($sessionKey) ? session($sessionKey) : self::SELF_AUTO_REFRESH;
        $this->realtimeDetailPolling($id, $autoRefresh);   //轮询js

        $b = Cabinet::find($cabinet['pid']);
        $refresh['autoRefresh'] = $autoRefresh;
        $refresh['key'] = $sessionKey;
        $refresh['title'] = $b['name'];
        $boxes = Cabinet::where('project_id', $projectId)->where('pid', 0)->get()->toArray();
        foreach ($boxes as &$oneBox) {
            $oneBox['url'] = url('admin/cabinet-realtime/'.$projectId.'/'.$oneBox['id']);
        }
        $refresh['boxes'] = $boxes;
        $refresh['status'] = WeconHandler::getBoxStatus($b['machine_code']);
        return $content
            ->body(headmenu($id))
            ->body(view('admin.cabinet.autoRefresh', $refresh))
            ->body($this->realtimeDetailView($cabinet));
    }

    protected function noRealtimeDetail($content, $name){
        return $content->header($name)
            ->description()
            ->body(function (Row $row) {
                // $row->column(2, $this->realtimeDetailMenuTree());
                $row->column(10, Card::make('暂 无 数 据'));
            });
    }

    protected function noRealtimeDetailData($content, $name){
        return $content->header($name)
            ->description()
            ->body(function (Row $row) {
                // $row->column(2, $this->realtimeDetailMenuTree());
                $row->column(10, Card::make('暂 无 数 据'));
            });
    }

    protected function realtimeDetailMenuTree($id){
        $cabinet = Cabinet::find($id);
        $projectId = $cabinet['project_id'];
        $parentId = $cabinet['pid'];

        $cabinets = Cabinet::select(['id', 'name', 'pid'])->where('project_id', $projectId)->get()->toArray();
        $menu = [];
        foreach ($cabinets as $k => $v) {
            if (!$v['pid']) {
                if ($v['id'] == $parentId) {
                    $one['spread'] = true;
                } else {
                    $one['spread'] = false;
                }
                $one['title'] = $v['name'];
                $one['id'] = $v['id'];
                $one['children'] = [];
                $one['isParent'] = true;
                $one['url'] = url('admin/cabinet-realtime').'/'.$projectId."/".$v['id'];
                foreach ($cabinets as $kk => $vv) {
                    if ($v['id'] == $vv['pid']) {
                        $children['spread'] = true;
                        $children['title'] = $vv['name'];
                        $children['id'] = $vv['id'];
                        $children['url'] = url('admin/cabinet-realtime-detail').'/'.$projectId.'/'.$vv['id'];
                        array_push($one['children'], $children);
                    }
                }
            array_push($menu, $one);
            }
        }
        $data['menu'] = json_encode($menu);
        $card = Card::make(view('admin.cabinet.realtimeMenuTree', $data));
        return $card;
    }

    protected function realtimeDetailView($cabinet){//$id, $points, $alias, $latestData
        $cabinets = Cabinet::where('pid', $cabinet['pid'])->where('show', Cabinet::SHOW_YES)->get()->toArray();
        $nav = [];
        foreach ($cabinets as $one) {
            $oneNav['name'] = $one['name'];
            $oneNav['url'] = url('admin/cabinet-realtime-detail').'/'.$one['project_id'].'/'.$one['id'];
            $oneNav['active'] = ($one['id'] == $cabinet['id']) ? 'active' : '';
            array_push($nav, $oneNav);
        }
        $data['nav'] = $nav;

        // if ($newestCache) {

        $cabinetData['time'] = date("Y-m-d H:i:s");
        $cabinetData['id'] = $cabinet['id'];

        $newestCacheKey = Cabinet::CACHE_KEY_.$cabinet['id'];
        $newestCache = Redis::get($newestCacheKey);
        if ($newestCache) {
            $newestData = json_decode($newestCache, true);

            $noShowPoint = CabinetPoint::where('cabinet_id', $cabinet['id'])->where('realtime_show', 0)->pluck('alias')->toArray();
            if ($noShowPoint) {
                foreach ($noShowPoint as $oneNoShow) {
                    unset($newestData[$oneNoShow]);
                }
            }

            $extraText = CabinetLiveText::getTextCache($newestData);
            if ($extraText) {
                foreach ($extraText as $alias => $name) {
                    $newestData[$alias] = $name;
                }
            }

            $cabinetData['newestData'] = $newestData;
        } else {
            $cabinetData['newestData'] = [];
        }
        $points = CabinetPoint::select(['id', 'alias', 'name', 'units', 'decimal'])->where('cabinet_id', $cabinet['id'])->get()->keyBy('alias')->toArray();
        $data['points'] = $points;
        $data['cabinetData'] = $cabinetData;
        $sessionKey = 'cabinet_realtime_detail_auto_refresh';
        $data['autoRefresh'] = session($sessionKey) ? session($sessionKey) : self::SELF_AUTO_REFRESH;
        $card = Card::make(view('admin.cabinet.realtimeDetail', $data));
        $card->padding('0');
        return $card;
    }

    protected function realtimeDetailPolling($id, $autoRefresh){
        $url = url('admin/getCabinetRealtimeDetailData');
        $token = csrf_token();
        Admin::script(
<<<JS
    Dcat.ready(function () {
        console.log('start polling');
        getCabinetRealtimeDetailData()

        function getCabinetRealtimeDetailData() {
            setTimeout(getCabinetRealtimeDetailData, 1000*$autoRefresh);

            let url = "$url";
            let data = {
                _token: '$token',
                id: $id
            }

            $.ajax({
                type : "POST",
                url : url,
                data : data,
                success : function(result) {
                    if (result.code == 1) {
                        const aliases = Object.keys(result.data.data)

                        var liveObj = $("div[id^='live-']");
                        if (liveObj.length > 0) {
                            liveObj.each(function(index, obj){
                                if ($.inArray( obj.id.split("-")[1], aliases ) === -1) {
                                    obj.remove();
                                }
                            })
                        }

                        // console.log(aliases)
                        for(let i=0;i<aliases.length;i++){
                            let pointElement = $("#"+aliases[i]);
                            if (pointElement.length === 0) {
                                var el = $('<div id="live-'+aliases[i]+'" class="single-card" style="box-shadow:1px 2px 6px #888888;width: 22%;margin:0.5rem;height: 16rem;"><div><div class="single-title" style="color:#FFFFFF;background:#3DA1E3; font-size: 22px;height:59px;line-height:59px;"><\/div><div name="points" class="single-content" style="text-align: center; font-size: 22px;height:172px;flex-direction:column;"><div style="width: 100%;color:#3CBE8B;font-size:35px;height:100%;"><div style="height:136px;line-height:50px;"><span id="'+aliases[i]+'"></span><\/div><div style="font-size: 18px; color:#666666;height:36px;" id="'+aliases[i]+'-time"><\/div><\/div><\/div><\/div><\/div>');

                                el.appendTo($("#left-card"));
                            }


                            $("#"+aliases[i]).html(result.data.data[aliases[i]])
                            $("#"+aliases[i]+"-time").html(result.data.time)
                        }
                    } else {
                        console.log(result.msg)
                    }
                },
                //请求失败，包含具体的错误信息
                error : function(e){
                    layer.close(e);
                    console.log(e.status);
                    console.log(e.responseText);
                }
            });
        }
    });
JS
);
    }

    public function getCabinetRealtimeDetailData(Request $request){
        $param = $request->all();

        $newestCacheKey = Cabinet::CACHE_KEY_.$param['id'];
        $newestCache = Redis::get($newestCacheKey);
        if ($newestCache) {
            $data['data'] = json_decode($newestCache, true);

            $noShowPoint = CabinetPoint::where('cabinet_id', $param['id'])->where('realtime_show', 0)->pluck('alias')->toArray();
            if ($noShowPoint) {
                foreach ($noShowPoint as $oneNoShow) {
                    unset($data['data'][$oneNoShow]);
                }
            }

            $points = CabinetPoint::select(['id', 'alias', 'name', 'units', 'decimal'])->where('cabinet_id', $param['id'])->get()->keyBy('alias')->toArray();
            foreach ($points as $alias => $one) {
                if ($one['decimal']) {
                    $data['data'][$alias] = round($data['data'][$alias] / pow(10, intval($one['decimal'])), 3);
                }
            }
            $data['time'] = date("Y-m-d H:i:s");

            $extraText = CabinetLiveText::getTextCache($data['data']);
            if ($extraText) {
                foreach ($extraText as $alias => $name) {
                    $data['data'][$alias] = $name;
                }
            }

            return response()->json(['code'=>1, 'data' => $data, 'msg' => 'success']);
        } else {
            return response()->json(['code'=>0, 'data' => '', 'msg' => 'no update']);
        }
    }

    public function setCabinetDetailData(Request $request)
    {
        $param = $request->all();
        $tmp = explode('_', $param['alias']);
        $monitorId = end($tmp);
        $res = WeconHandler::setData($monitorId, $param['value']);
        if (!$res && $res !== false) {
            return response()->json(['code'=>1, 'msg' => 'success']);
        } else {
            if (isset($res['error'])) {
                return response()->json(['code'=>0, 'msg' => $res['error']]);
            } else {
                return response()->json(['code'=>0, 'msg' => '修改失败']);
            }
        }
    }

    //*************************************************************************************************
    //*************************************************************************************************
    
    public function monitor(Content $content, $id = 0)
    {   
        Admin::css('/layui/css/layui.css');
        $sessionKey = 'cabinet_monitor_auto_refresh';
        $autoRefresh = session($sessionKey) ? session($sessionKey) : self::SELF_AUTO_REFRESH;

        $info = explode('-', $id);
        $cabinetId = reset($info);
        $alias = end($info);
        
        $cabinet = Cabinet::find($cabinetId);
        
        $b = Cabinet::find($cabinet['pid']);
        $refresh['autoRefresh'] = $autoRefresh;
        $refresh['key'] = $sessionKey;
        $refresh['title'] = $b['name'];
        $boxes = Cabinet::where('project_id', $cabinet['project_id'])->where('pid', 0)->get()->toArray();
        foreach ($boxes as &$oneBox) {
            $oneBox['url'] = url('admin/cabinet-realtime/'.$cabinet['project_id'].'/'.$oneBox['id']);
        }
        $refresh['boxes'] = $boxes;
        $refresh['status'] = WeconHandler::getBoxStatus($b['machine_code']);
        return $content
            // ->header($cabinet['name'].'-'.$point)
            ->body(headmenu($cabinetId,1))
            ->body(view('admin.cabinet.autoRefresh', $refresh))
            ->body($this->monitorView($cabinet, $alias));
    }

    protected function monitorView($cabinet, $alias){
        $page = 1;
        $size = 1000;

        $data['cabinet'] = $cabinet;
        $data['page'] = $page;

        $cabinets = Cabinet::where('pid', $cabinet['pid'])->where('show', Cabinet::SHOW_YES)->get()->toArray();
        $cabinetNav = [];
        foreach ($cabinets as $one) {
            $firstPoint = CabinetPoint::select('alias')->where('cabinet_id', $one['id'])->first()->toArray();
            $oneCabinetNav['name'] = $one['name'];
            $oneCabinetNav['url'] = url('admin/cabinet-monitor').'/'.$one['id'].'-'.$firstPoint['alias'];
            $oneCabinetNav['active'] = ($one['id'] == $cabinet['id']) ? 'active' : '';
            array_push($cabinetNav, $oneCabinetNav);
        }
        $data['cabinetNav'] = $cabinetNav;

        $pointNav = [];
        $points = CabinetPoint::where('cabinet_id', $cabinet['id'])->pluck('name', 'alias')->toArray();
        foreach ($points as $pointAlias => $pointName) {
            $onePointNav['name'] = $pointName;
            $onePointNav['url'] = url('admin/cabinet-monitor').'/'.$cabinet['id'].'-'.$pointAlias;
            $onePointNav['active'] = ($alias == $pointAlias) ? 'active' : '';
            array_push($pointNav, $onePointNav);
        }
        $data['pointNav'] = $pointNav;

        $headerData = $this->getMonitorData($cabinet, $alias);
        $data['headerData'] = $headerData;

        $chartData = [];
        $start = strtotime(date("Y-m-d"));
        // $start = 1656487217;
        $end = time();
        
        $data['start'] = $start;
        $data['end'] = $end;

        $d = CabinetDataSecond::getJsonDataListPaging($cabinet['id'], $alias, $start, $end, $page, $size);

        $xData = [];
        $yData = [];
        foreach ($d as $one) {
            $one = json_decode( json_encode( $one ),true);
            $xData[] = date("H:i:s", $one['created_time']);
            $yData[] = $one[$alias];
        }
        $chartData['cabinet'] = $cabinet['id'];
        $chartData['alias'] = $alias;
        if ($d) {
            $endPoint = json_decode( json_encode( end($d) ),true);
            $chartData['endX'] = $endPoint['created_time'];
        } else {
            $chartData['endX'] = time();
        }
        $chartData['startValue'] = date("H:i:s", strtotime('-30 minute', $chartData['endX']));
        $chartData['xData'] = json_encode($xData);
        $chartData['yData'] = json_encode($yData);

        $data['chartData'] = $chartData;

        $sessionKey = 'cabinet_monitor_auto_refresh';
        $data['autoRefresh'] = session($sessionKey) ? session($sessionKey) : self::SELF_AUTO_REFRESH;
        $data['alias'] = $alias;

        $card = Card::make(view('admin.cabinet.monitorData', $data));
        $card->padding('0');
        return $card;
    }

    protected function initCabinetMonitorChart(Request $request){
        $size = 1000;
        $param = $request->all();

        $d = CabinetDataSecond::getJsonDataListPaging($param['cabinetId'], $param['alias'], $param['start'], $param['end'], $param['page'], $size);

        if (empty($d)) {
            return response()->json(['code'=>0, 'data' => [], 'msg' => 'no data']);
        }

        $xData = [];
        $yData = [];
        foreach ($d as $one) {
            $one = json_decode( json_encode( $one ),true);
            $xData[] = date("H:i", $one['created_time']);
            $yData[] = $one[$param['alias']];
        }
        $data['xData'] = $xData;
        $data['yData'] = $yData;
        $data['page'] = $param['page'];

        return response()->json(['code'=>1, 'data' => $data, 'msg' => 'success']);
    }

    protected function pollingCabinetMonitorData(Request $request){
        $param = $request->all();
        
        $data = [];

        $newestCacheKey = Cabinet::CACHE_KEY_.$param['cabinetId'];
        $newestCache = Redis::get($newestCacheKey);
        if ($newestCache) {
            $newestData = json_decode($newestCache, true);

            $data['now'] = round($newestData[$param['alias']], 3);
            $xData[] = date("H:i:s");
            $yData[] = $data['now'];
            $data['xData'] = $xData;
            $data['yData'] = $yData;
            $data['alias'] = $param['alias'];
        }
        if ($data) {
            return response()->json(['code'=>1, 'data' => $data, 'msg' => 'success']);
        } else {
            return response()->json(['code'=>0, 'data' => [], 'msg' => 'no data']);
        }
    }

    protected function monitorMenuTree($cabinet){
        $projectId = $cabinet['project_id'];

        $cabinets = Cabinet::select(['id', 'name', 'pid'])->where('project_id', $projectId)->get()->toArray();
        $menu = [];
        //盒子
        foreach ($cabinets as $k => $v) {
            if (!$v['pid']) {
                $one['spread'] = true;
                $one['title'] = $v['name'];
                $one['id'] = $v['id'];
                $one['children'] = [];
                $one['isParent'] = true;
                $one['url'] = url('admin/cabinet-realtime').'/'.$projectId.'/'.$v['id'];
                //设备(电源柜)
                foreach ($cabinets as $kk => $vv) {
                    if ($v['id'] == $vv['pid']) {
                        if ($vv['id'] == $cabinet['id']) {
                            $children['spread'] = true;
                        } else {
                            $children['spread'] = false;
                        }
                        $children['title'] = $vv['name'];
                        $children['id'] = $vv['id'];
                        $children['isParent'] = true;
                        $children['url'] = url('admin/cabinet-realtime-detail').'/'.$projectId.'/'.$vv['id'];
                        $children['children'] = [];
                        $points = CabinetPoint::where('cabinet_id', $vv['id'])->pluck('name', 'alias')->toArray();
                        //采集点
                        foreach ($points as $key => $value) {
                            $c['spread'] = true;
                            $c['title'] = $value;
                            $c['id'] = $vv['id'].'-'.$key;
                            $c['url'] = url('admin/cabinet-monitor').'/'.$c['id'];
                            array_push($children['children'], $c);
                        }
                        array_push($one['children'], $children);
                    }
                }
            array_push($menu, $one);
            }
        }
        $data['menu'] = json_encode($menu);
        $card = Card::make(view('admin.cabinet.monitorMenuTree', $data));
        return $card;
    }

    protected function monitorData(){//$cabinet, $alias
        // $data = $this->getMonitorData($cabinet['id'], $alias);
        $sessionKey = 'cabinet_monitor_auto_refresh';
        $data['autoRefresh'] = session($sessionKey) ? session($sessionKey) : self::SELF_AUTO_REFRESH;
        $card = Card::make(view('admin.cabinet.monitorData', $data));
        return $card;
    }

    protected function getMonitorData($cabinet, $alias, $latestTime = null){
        $latest = CabinetDataSecond::getJsonDataOne($cabinet['id'], [$alias, 'created_time'], $latestTime);

        if (!$latest) {
            return [];
        }

        $data['now'] = $latest[$alias];
        $data['time'] = date("Y-m-d H:i:s", $latest['created_time']);

        $start = strtotime(date("Y-m-d"));
        $end = time();

        $data['max'] = CabinetDataSecond::getMax($cabinet['id'], $alias, $start, $end);
        $data['min'] = CabinetDataSecond::getMin($cabinet['id'], $alias, $start, $end);
        $data['avg'] = CabinetDataSecond::getAvg($cabinet['id'], $alias, $start, $end);

        $data['alias'] = $alias;
        $data['cabinetId'] = $cabinet['id'];

        return $data;
    }

    public function getCabinetMonitorData(Request $request){
        $param = $request->all();
        $cabinet = Cabinet::find($param['cabinetId']);
        $data = $this->getMonitorData($cabinet, $param['alias'], $param['time']);
        if (empty($data)) {
            return response()->json(['code'=>0, 'data' => '', 'msg' => 'no update']);
        } else {
            return response()->json(['code'=>1, 'data' => $data, 'msg' => 'success']);
        }
    }

    protected function monitorChart(){//$cabinet, $alias
        $start = strtotime(date("Y-m-d"));
        $end = time();

        // $d = CabinetData::getJsonDataList($cabinet['id'], $alias, $start, $end);
        // $xData = [];
        // $yData = [];
        // foreach ($d as $one) {
        //     $one = json_decode( json_encode( $one ),true);
        //     $xData[] = date("H:i", $one['created_time']);
        //     $yData[] = $one[$alias];
        // }
        // $data['cabinet'] = $cabinet;
        // $data['alias'] = $alias;
        // if ($d) {
        //     $endPoint = json_decode( json_encode( end($d) ),true);
        //     $data['endX'] = $endPoint['created_time'];
        // } else {
        //     $data['endX'] = time();
        // }
        // $data['startValue'] = date("H:i", strtotime('-30 minute', $data['endX']));
        // $data['xData'] = json_encode($xData);
        // $data['yData'] = json_encode($yData);
        $data['xData'] = 10;
        $data['yData'] = 10;
        $sessionKey = 'cabinet_monitor_auto_refresh';
        $data['autoRefresh'] = session($sessionKey) ? session($sessionKey) : self::SELF_AUTO_REFRESH;        
        $card = Card::make(view('admin.cabinet.monitorChart', $data));
        return $card;
    }

    public function getCabinetMonitorChart(Request $request){
        $param = $request->all();
        $time = strtotime(date("Y-m-d")." ". $param['endX']. ":00");

        $d = CabinetData::getJsonDataList($param['cabinetId'], $param['alias'], $param['endX']);
        if ($d) {
            $xData = [];
            $yData = [];
            foreach ($d as $one) {
                $one = json_decode( json_encode( $one ),true);
                $xData[] = date("H:i", $one['created_time']);
                $yData[] = $one[$param['alias']];
            }
            $data['xData'] = $xData;
            $data['yData'] = $yData;
            $endPoint = json_decode( json_encode( end($d) ),true);
            $data['endX'] = $endPoint['created_time'];
            return response()->json(['code'=>1, 'data' => $data, 'msg' => 'success']);
        } else {
            return response()->json(['code'=>0, 'data' => [], 'msg' => 'no update']);
        }
    }

    //*************************************************************************************************
    //*************************************************************************************************
    
    public function history(Request $request, Content $content, $id = 0)
    {   
        Admin::css('/layui/css/layui.css');
        Admin::script(
            <<<JS
    var table = document.getElementById('grid-table');
    table.style.cssText="background-color:#e3e5eb;"
JS            
        );
        $ids = json_decode($id,true);
        if (json_last_error() == JSON_ERROR_NONE && is_array($ids)) {    //监测点
            $checkedPoints = $ids;
            $tmp = explode('-', reset($checkedPoints));
            $cabinet = Cabinet::find($tmp[0]);
            $box = $cabinet['pid'];
        } else {    //盒子
            $tmp = explode('-', $id);
            $box = $tmp[0];
            $cabinet = [];
            if (isset($tmp[1])) {
                $cabinet = Cabinet::find($tmp[1]);
            }
            $checkedPoints = [];
        }

        return $content
            ->body(headmenu($box,2))
            ->body($this->historyView($box, $cabinet, $checkedPoints, $request));
    }

    protected function historyView($box, $cabinet, $checkedPoints, $request){
        $data['box'] = Cabinet::find($box);  
        $cabinets = Cabinet::where('pid', $box)->where('show', Cabinet::SHOW_YES)->get()->toArray();
        if (empty($cabinet)) {
            $cabinet = reset($cabinets);
        }
        $data['cabinet'] = $cabinet;

        $param = $request->all();

        $cabinetNav = [];
        foreach ($cabinets as $k => $one) {
            $oneCabinetNav['name'] = $one['name'];
            $oneCabinetNav['url'] = url('admin/cabinet-history').'/'.$box.'-'.$one['id'];
            $oneCabinetNav['active'] = ($one['id'] == $cabinet['id']) ? 'active' : '';
            array_push($cabinetNav, $oneCabinetNav);
        }
        $data['cabinetNav'] = $cabinetNav;
 
        $pointNav = [];
        $tmpCheckedPoints = [];
        foreach ($checkedPoints as $oneCheckedPoint) {
            $tmpOneCheckedPoint = explode('-', $oneCheckedPoint);
            $tmpCheckedPoints[] = $tmpOneCheckedPoint[1];
        }

        $points = CabinetPoint::where('cabinet_id', $cabinet['id'])->pluck('name', 'alias')->toArray();
        foreach ($points as $pointAlias => $pointName) {
            $onePointNav['name'] = $pointName;
            $onePointNav['active'] = in_array($pointAlias, $tmpCheckedPoints) ? 'active' : '';
            $onePointNav['alias'] = $pointAlias;
            array_push($pointNav, $onePointNav);
        }
        $data['pointNav'] = $pointNav;
        $data['points'] = $points;
        $data['url'] = $request->url();

        $grid = $this->historyGrid($cabinet, $tmpCheckedPoints, $points);
        $data['grid'] = $grid;
        
        $lineData = $this->historyLine($cabinet, $tmpCheckedPoints, $points, $request);
        $data = array_merge($data, $lineData);

        $card = Card::make(view('admin.cabinet.historyData', $data));
        $card->padding('0');
        return $card;
    }

    protected function getNewHistoryUrl(Request $request){
        $param = $request->all();
        $currentUrl = urldecode($param['currentUrl']);
        $tmp = explode('/', $currentUrl);
        $id = end($tmp);
        $ids = json_decode($id,true);
        if (json_last_error() == JSON_ERROR_NONE && is_array($ids)) {    //监测点
            $checkedPoints = $ids;
            $tmp = explode('-', reset($checkedPoints));
            $cabinet = Cabinet::find($tmp[0]);
            $box = $cabinet['pid'];
        } else {    //盒子
            $tmp = explode('-', $id);
            $box = $tmp[0];
            $cabinet = [];
            if (isset($tmp[1])) {
                $cabinet = Cabinet::find($tmp[1]);
            }
            $checkedPoints = [];
        }
        if (empty($cabinet)) {
            $cabinet = Cabinet::where('pid', $box)->first();
        }
        $alias = $cabinet['id'].'-'.$param['alias'];
        //选中或不选中
        if (in_array($alias, $checkedPoints)) {
            $k = array_search($alias , $checkedPoints);
            unset($checkedPoints[$k]);
        } else {
            $checkedPoints[] = $alias;
        }

        if (empty($checkedPoints)) {
            $url = url('admin/cabinet-history').'/'.$box.'-'.$cabinet['id'];
        } else {
            $url = url('admin/cabinet-history').'/'.json_encode($checkedPoints);
        }
        $data['url'] = $url;
        return response()->json(['code'=>1, 'data' => $data, 'msg' => 'success']);
    }

    protected function historyMenuTree($checkedIds = null){
        if (is_array($checkedIds)) {
            $info = explode('-',reset($checkedIds));
            $cabinetId = reset($info);
            $cabinet = Cabinet::find($cabinetId);
            $projectId = $cabinet['project_id'];
            $pid = $cabinet['pid'];
        } else {
            $cabinet = Cabinet::find($checkedIds);
            $projectId = $cabinet['project_id'];
            $pid = $cabinet['id'];
        }

        $menu = [];
        $cabinets = Cabinet::select(['id', 'name', 'pid'])->where('project_id', $projectId)->get()->toArray();

        foreach ($cabinets as $k => $v) {
            if (!$v['pid']) {
                if ($v['id'] == $pid) {
                    $one['spread'] = true;
                } else {
                    $one['spread'] = false;
                }
                $one['title'] = $v['name'];
                $one['id'] = $v['id'];
                $one['children'] = [];
                $one['isParent'] = true;
                $one['url'] = url('admin/cabinet-realtime').'/'.$projectId."/".$v['id'];
                foreach ($cabinets as $kk => $vv) {
                    if ($v['id'] == $vv['pid']) {
                        if ($vv['id'] == $cabinet['id']) {
                            $children['spread'] = true;
                        } else {
                            $children['spread'] = false;
                        }
                        $children['title'] = $vv['name'];
                        $children['id'] = $vv['id'];
                        $children['url'] = url('admin/cabinet-realtime-detail').'/'.$projectId.'/'.$vv['id'];
                        
                        $children['children'] = [];
                        $points = CabinetPoint::where('cabinet_id', $vv['id'])->where('history_show', 1)->get()->toArray();
                        if ($points) {
                            foreach ($points as $key => $onePoint) {
                                $c['spread'] = false;
                                $c['title'] = $onePoint['name'];
                                $c['id'] = $vv['id'].'-'.$onePoint['alias'];
                                array_push($children['children'], $c);
                            }
                        }
                        array_push($one['children'], $children);
                    }
                }
            array_push($menu, $one);
            }
        }

        if ($checkedIds && is_array($checkedIds)) {
            $data['checkedIds'] = json_encode($checkedIds);
        } else {
            $data['checkedIds'] = json_encode([]);
        }

        $data['menu'] = json_encode($menu);
        $card = Card::make(view('admin.cabinet.historyMenuTree', $data));
        return $card;
    }

    protected function historyGrid($cabinet, $fields, $aliasNames){
        $m = CabinetDataSecond::select(['data', 'created_time'])->where('cabinet_id', $cabinet['id'])->orderBy('created_time', 'desc');
        
        if (empty($fields)) {
            $m = CabinetData::select(['data', 'created_time'])->where('cabinet_id', 0)->orderBy('created_time', 'desc');
        }
        return Grid::make($m, function (Grid $grid) use ($fields, $aliasNames) {
            $grid->setActionClass(Grid\Displayers\Actions::class);
            $grid->column('created_time','上报时间');
            $grid->column('created_time','上报时间')->display(function ($time) {
                return date("Y-m-d H:i:s", $time);
            });

            foreach ($fields as $alias) {
                $grid->column($alias, $aliasNames[$alias])->display(function ($v) use($alias) {
                    $t = json_decode($this->data, true);
                    if (isset($t[$alias])) {
                        return $t[$alias];
                    } else {
                        return 0;
                    }
                });
            }

            $grid->disableCreateButton();
            $grid->disableEditButton();
            $grid->disableViewButton();

            $grid->showFilter();
            $grid->showFilterButton();
            $grid->filter(function($filter){
                // 展开过滤器
                $filter->panel();
                $filter->between('created_time', '上报时间')->datetime()->toTimestamp();
            });
            // $grid->export();
            $grid->export()->rows(function ($rows) use($fields) {
                foreach ($rows as $index => &$row) {
                    $row['created_time'] = date("Y-m-d H:i:s", $row['created_time']);
                    foreach ($fields as $alias) {
                        $row[$alias] = json_decode($row['data'], true)[$alias];
                    }
                }
                return $rows;
            });
            $grid->export()->filename('历史数据-'.time());
        });
    }

    protected function historyLine($cabinet, $tmpCheckedPoints, $points, $request){
        $xData = [];
        $legend = [];
        $series = [];

        $param = $request->all();
        if (isset($param['created_time'])) {
            $start = strtotime($param['created_time']['start']);
            $end = strtotime($param['created_time']['end']);
        } else {
            $start = 0;
            $end = 0;
        }
        if (isset($param['per_page'])) {
            $size = $param['per_page'];
        } else {
            $size = 20;
        }
        if (isset($param['page'])) {
            $page = $param['page'];
        } else {
            $page = 1;
        }

        $d = CabinetDataSecond::getJsonDataListPaging($cabinet['id'], $tmpCheckedPoints, $start, $end, $page, $size);

        foreach ($d as $oneD) {
            $oneRecord = json_decode( json_encode( $oneD ),true);
            $xData[] = date("Y/m/d H:i:s", $oneRecord['created_time']);
            foreach ($tmpCheckedPoints as $oneTmpCheckedPoints) {
                if (isset($oneRecord[$oneTmpCheckedPoints])) {
                    $$oneTmpCheckedPoints[] = $oneRecord[$oneTmpCheckedPoints];
                } else {
                    $$oneTmpCheckedPoints[] = 0;
                }
            }
        }

        foreach ($tmpCheckedPoints as $oneTmpCheckedPoints) {
            $legend[] = $points[$oneTmpCheckedPoints];
            $oneSeries['name'] = $points[$oneTmpCheckedPoints];
            $oneSeries['type'] = 'line';
            $oneSeries['data'] = isset($$oneTmpCheckedPoints) ? $$oneTmpCheckedPoints : [];
            array_push($series, $oneSeries);
        }

        $data['xData'] = json_encode($xData);
        $data['series'] = json_encode($series);
        $data['legend'] = json_encode($legend);
        return $data;
    }

    public function destroy($idx, $id){
        $form = Form::make(new CabinetData(), function (Form $form) {});
        return $form->destroy($id);
    }

    //*************************************************************************************************
    //*************************************************************************************************
    
    public function compare(Content $content, $id = 0)
    {       
        Admin::css('https://www.layuicdn.com/layui/css/layui.css');
        $id = json_decode($id,true);
        if (is_array($id) && !empty($id)) {    //监测点
            $checkedPoints = $id;
            $treeCard = $this->compareMenuTree($checkedPoints);
        } else {    //盒子id
            if (empty($id)) {
                $id = session('tmpbox');
            } else {
                session()->put('tmpbox', $id);
            }
            $treeCard = $this->compareMenuTree($id);
            $checkedPoints = null;
        }

        $yesterday = date("Y-m-d", strtotime("-1 day"));
        $compareDate = session('compare_date') ? session('compare_date') : $yesterday;
        return $content
            ->header('历史曲线')
            ->description(view('admin.cabinet.compareDateSelect',['compareDate' => $compareDate]))
            ->body(function (Row $row) use ($treeCard, $checkedPoints) {
                $row->column(2, $treeCard);
                if (is_array($checkedPoints) && !empty($checkedPoints)) {
                    $cabinets = [];
                    foreach ($checkedPoints as $oneCheckedPoint) {
                        $info = explode('-',$oneCheckedPoint);
                        $cabinetId = reset($info);
                        $alias = end($info);
                        $cabinets[$cabinetId][] = $alias;
                    }
                    $row->column(10, function (Column $column) use ($cabinets) {
                        $column->row(function(Row $row) use ($cabinets) {
                            foreach ($cabinets as $id => $points) {
                                $row->column(12, $this->compareChart($id, $points));
                            }
                        });
                    });
                }
            });
    }

    protected function compareMenuTree($checkedIds = null){
        if (is_array($checkedIds)) {
            $info = explode('-',reset($checkedIds));
            $cabinetId = reset($info);
            $cabinet = Cabinet::find($cabinetId);
            $projectId = $cabinet['project_id'];
            $pid = $cabinet['pid'];
        } else {
            $cabinet = Cabinet::find($checkedIds);
            $projectId = $cabinet['project_id'];
            $pid = $cabinet['id'];
        }

        $cabinets = Cabinet::select(['id', 'name', 'pid'])->where('project_id', $projectId)->get()->toArray();
        $menu = [];

        foreach ($cabinets as $k => $v) {
            if (!$v['pid']) {
                if ($v['id'] == $pid) {
                    $one['spread'] = true;
                } else {
                    $one['spread'] = false;
                }
                $one['title'] = $v['name'];
                $one['id'] = $v['id'];
                $one['children'] = [];
                $one['isParent'] = true;
                $one['url'] = url('admin/cabinet-realtime').'/'.$projectId."/".$v['id'];
                foreach ($cabinets as $kk => $vv) {
                    if ($v['id'] == $vv['pid']) {
                        if ($vv['id'] == $cabinet['id']) {
                            $children['spread'] = true;
                        } else {
                            $children['spread'] = false;
                        }
                        $children['title'] = $vv['name'];
                        $children['id'] = $vv['id'];
                        $children['url'] = url('admin/cabinet-realtime-detail').'/'.$projectId.'/'.$vv['id'];
                        
                        $children['children'] = [];
                        $points = CabinetPoint::where('cabinet_id', $vv['id'])->where('history_line_show', 1)->get()->toArray();
                        if ($points) {
                            foreach ($points as $key => $onePoint) {
                                $c['spread'] = false;
                                $c['title'] = $onePoint['name'];
                                $c['id'] = $vv['id'].'-'.$onePoint['alias'];
                                array_push($children['children'], $c);
                            }
                        }
                        array_push($one['children'], $children);
                    }
                }
            array_push($menu, $one);
            }
        }

        if ($checkedIds && is_array($checkedIds)) {
            $data['checkedIds'] = json_encode($checkedIds);
        } else {
            $data['checkedIds'] = json_encode([]);
        }
        $data['menu'] = json_encode($menu);
        $card = Card::make(view('admin.cabinet.compareTree', $data));
        return $card;
    }

    protected function compareChart($cabinetId, $points){
        $cabinet = Cabinet::find($cabinetId);
        $aliasNames = CabinetPoint::where('cabinet_id', $cabinetId)->whereIn('alias', $points)->pluck('name','alias')->toArray();

        $yesterday = date("Y-m-d", strtotime("-1 day"));
        $date = session('compare_date') ? session('compare_date') : $yesterday;

        $start = strtotime($date);
        $end = strtotime("+1 day", $start);

        $d = CabinetData::getJsonDataList($cabinetId, $points, $start, $end);

        if (empty($d)) {
            $card = Card::make('暂无数据');
            return $card;
        }

        foreach ($d as $one) {
            $one = json_decode( json_encode( $one ),true);
            $xData[] = date("H:i", $one['created_time']);
            foreach ($points as $onePoint) {
                $$onePoint[] = $one[$onePoint];
            }
        }

        $legend = [];
        $series = [];
        foreach ($points as $onePoint) {
            $legend[] = $aliasNames[$onePoint];
            
            $oneSeries['name'] = $aliasNames[$onePoint];
            $oneSeries['type'] = 'line';
            //$oneSeries['stack'] = 'Total';
            $oneSeries['data'] = $$onePoint;
            array_push($series, $oneSeries);
        }

        $data['xData'] = json_encode($xData);
        $data['series'] = json_encode($series);
        $data['legend'] = json_encode($legend);
        $data['cabinet'] = $cabinet;
        $data['startValue'] = date("H:i", strtotime("-1 hours", $end));

        $card = Card::make(view('admin.cabinet.compareChart', $data));
        return $card;
    }

    //*************************************************************************************************
    //*************************************************************************************************

    public function custom(Content $content, $projectId, $id = 0)
    {   
        Admin::css('/layui/css/layui.css');
        // headmenu($projectId,3);
        $box = Cabinet::find($id);
        return $content
            ->body(headmenu($id,3))
            ->description()
            ->body(function (Row $row) use ($box) {
                $row->column(12, function (Column $column) use ($box) {
                    $column->row($this->customChart($box));
                });
            });
    }

    public function customChart($box){
        $cabinets = Cabinet::where('pid', $box['id'])->where('show', Cabinet::SHOW_YES)->pluck('name', 'id')->toArray();
        $data['cabinets'] = $cabinets;
        $data['xData'] = json_encode([]);
        $data['yData'] = json_encode([]);
        $card = Card::make(view('admin.cabinet.custom', $data));
        return $card;
    }

    public function getPointsByCabinetId(Request $request){
        $param = $request->all();

        $points = CabinetPoint::where('cabinet_id', $param['id'])->pluck('name', 'alias')->toArray();

        $data['points'] = $points;
        return response()->json(['code'=>1, 'data' => $points, 'msg' => 'success']);
    }

    public function getChartByPoint(Request $request){
        $param = $request->all();
        $end = time();
        $start = strtotime('-1 hour');

        $cabinet = Cabinet::find($param['cabinetId']);
        $d = CabinetDataSecond::getJsonDataList($param['cabinetId'], [$param['x'], $param['y']], $start, $end);
    
        $xData = [];
        $yData = [];
        foreach ($d as $one) {
            $one = json_decode( json_encode( $one ),true);
            $xData[] = round($one[$param['x']], 3);
            $time = date("H:i:s", $one['created_time']);
            // $yData[] = round($one[$param['y']], 3);
            $yData[] = ['time' => $time, 'value' => round($one[$param['y']], 3)];
        }
        $data['xData'] = $xData;
        $data['yData'] = $yData;
        return response()->json(['code'=>1, 'data' => $data, 'msg' => 'success']);
    }
}
